package com.nineclock.system.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.excel.EasyExcel;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.nineclock.common.entity.PageResult;
import com.nineclock.common.enums.ResponseEnum;
import com.nineclock.common.exception.NcException;
import com.nineclock.common.threadlocal.CurrentUserHolder;
import com.nineclock.common.utils.BeanHelper;
import com.nineclock.system.config.HxImManager;
import com.nineclock.system.dto.SysCompanyUserDTO;
import com.nineclock.system.dto.SysDepartmentDTO;
import com.nineclock.system.dto.SysRoleDTO;
import com.nineclock.system.excel.ExcelMember;
import com.nineclock.system.excel.MemberListener;
import com.nineclock.system.mapper.*;
import com.nineclock.system.pojo.*;
import com.nineclock.system.service.SysCompanyUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author 黑马程序员
 * @Company http://www.ithiema.com
 * @Version 1.0
 */
@Service
@Transactional
public class SysCompanyUserServiceImpl implements SysCompanyUserService {

    @Autowired
    SysCompanyUserMapper companyUserMapper;

    @Autowired
    SysCompanyUserRoleMapper companyUserRoleMapper;

    @Autowired
    SysRoleMapper roleMapper;

    @Autowired
    SysDepartmentMapper departmentMapper;

    @Autowired
    SysCompanyMapper companyMapper;

    @Override
    public List<SysCompanyUserDTO> queryCompanyUser(Long companyId, Long userId) {
        //健壮性的判断
        if(companyId == null && userId == null){
            throw new NcException(ResponseEnum.INVALID_PARAM_ERROR);
        }

        LambdaQueryWrapper<SysCompanyUser> companyUserQw = new LambdaQueryWrapper<>();
        //判断是否是有效的员工信息
        companyUserQw.eq(SysCompanyUser::getEnable, 1);
        if(userId != null){
            companyUserQw.eq(SysCompanyUser::getUserId, userId);
        }

        if(companyId != null){
            companyUserQw.eq(SysCompanyUser::getCompanyId, companyId);
        }
        //查询得到员工列表
        List<SysCompanyUser> companyUserList = companyUserMapper.selectList(companyUserQw);

        //健壮性的判断
        if(CollectionUtil.isEmpty(companyUserList)){
            throw new NcException(ResponseEnum.USER_NOT_JOIN_COMPANY);
        }

        //转换为DTO列表
        List<SysCompanyUserDTO> companyUserDTOList = BeanHelper.copyWithCollection(companyUserList, SysCompanyUserDTO.class);

        //组装角色信息
        companyUserDTOList.forEach(companyUserDTO -> {
            //根据每一个员工获取对应的角色信息
            LambdaQueryWrapper<SysCompanyUserRole> companyUserRoleQw = new LambdaQueryWrapper<>();
            companyUserRoleQw.eq(SysCompanyUserRole::getCompanyUserId,companyUserDTO.getId() );
            companyUserRoleQw.eq(SysCompanyUserRole::getCompanyId, companyUserDTO.getCompanyId());

            List<SysCompanyUserRole> companyUserRoleList = companyUserRoleMapper.selectList(companyUserRoleQw);
            if(CollectionUtil.isNotEmpty(companyUserRoleList)){
                //把中间的中的角色id取出来
                Set<Long> roleIds = companyUserRoleList.stream().map(sysCompanyUserRole -> {
                    return sysCompanyUserRole.getRoleId();
                }).collect(Collectors.toSet());


                LambdaQueryWrapper<SysRole> roleQw = new LambdaQueryWrapper<>();
                roleQw.in(SysRole::getId, roleIds);

                List<SysRole> roleList = roleMapper.selectList(roleQw);
                //转换为DTO数据
                List<SysRoleDTO> sysRoleDTOS = BeanHelper.copyWithCollection(roleList, SysRoleDTO.class);

                companyUserDTO.setRoles(sysRoleDTOS);

            }

        });

        return companyUserDTOList;
    }

    @Override
    public List<SysCompanyUserDTO> queryCompanyMemberList() {
        //获取当前企业id
        Long companyId = CurrentUserHolder.get().getCompanyId();

        LambdaQueryWrapper<SysCompanyUser> companyUserQw = new LambdaQueryWrapper<>();
        companyUserQw.eq(SysCompanyUser::getCompanyId, companyId);
        companyUserQw.eq(SysCompanyUser::getEnable, 1);
        //不是当前管理员
        Long companyUserId = CurrentUserHolder.get().getCompanyUserId();
        companyUserQw.ne(SysCompanyUser::getId, companyUserId);

        //查询员工列表
        List<SysCompanyUser> companyUserList = companyUserMapper.selectList(companyUserQw);
        if(CollectionUtil.isEmpty(companyUserList)){
            throw new NcException(ResponseEnum.USER_NOT_FOUND);
        }

        //转换数据
        List<SysCompanyUserDTO> companyUserDTOList = BeanHelper.copyWithCollection(companyUserList, SysCompanyUserDTO.class);


        return companyUserDTOList;
    }

    @Override
    public PageResult<SysCompanyUserDTO> queryMembers(Integer page, Integer pageSize, String keyword, Long departmentId) {
        //查询当前部门下的所有的子部门的id集合(包含当前部门id ，子部门id)

        Set<Long> departmentIds = new HashSet<>();
        //如果前端部门id为0 ，查询所有的部门id
        if(departmentId == 0){
            departmentIds = this.queryAllDepartmentId();
        }else{
            //查询当前部门的子部门id
            //添加当前部门的id
            departmentIds.add(departmentId);
            this.queryChildrenDepartmentIds(departmentIds, departmentId);
        }


        //定义员工的queryWrapper对象
        LambdaQueryWrapper<SysCompanyUser> companyUserQw = new LambdaQueryWrapper<>();
        companyUserQw.eq(SysCompanyUser::getCompanyId, CurrentUserHolder.get().getCompanyId());
        companyUserQw.in(SysCompanyUser::getDepartmentId, departmentIds);
        //分页模型对象（要求包含 当前页 ，每页条数）
        Page<SysCompanyUser> companyUserPage = new Page(page , pageSize);

        //keyword
        if(StrUtil.isNotEmpty(keyword)){
            companyUserQw.and(queryWrapper -> {
                queryWrapper.like(SysCompanyUser::getUserName, keyword)
                        .or().like(SysCompanyUser::getWorkNumber, keyword)
                        .or().like(SysCompanyUser::getMobile, keyword);
            });
        }
        //分页查询
        companyUserPage = companyUserMapper.selectPage(companyUserPage, companyUserQw);
        List<SysCompanyUser> records = companyUserPage.getRecords();
        List<SysCompanyUserDTO> companyUserDTOList = BeanHelper.copyWithCollection(records, SysCompanyUserDTO.class);
        for (SysCompanyUserDTO companyUserDTO : companyUserDTOList) {
            //创建部门对象
            SysDepartmentDTO departmentDTO = new SysDepartmentDTO();
            departmentDTO.setId(companyUserDTO.getDepartmentId());
            departmentDTO.setName(companyUserDTO.getDepartmentName());
            //放到员工属性中
            companyUserDTO.setDepartment(departmentDTO);
        }

        //封装PageResult对象
        return new PageResult(companyUserPage.getTotal(),
                companyUserPage.getPages(), companyUserDTOList);
    }

    @Override
    public void importData(MultipartFile excelFile) throws IOException {
        if(excelFile == null){
            throw new NcException(ResponseEnum.FILE_UPLOAD_ERROR);
        }
        EasyExcel.read(
                excelFile.getInputStream(),
                ExcelMember.class,
                new MemberListener(this))
                .sheet(0).doRead();
    }

    @Autowired
    HxImManager manager;

    @Autowired
    SysUserMapper userMapper;
    @Override
    public void handlerData(List<ExcelMember> members) {
        for (ExcelMember member : members) {
            //判断工号是否 存在
            if(member.getWorkNumber() != null){
                LambdaQueryWrapper<SysCompanyUser> companyUserQw = new LambdaQueryWrapper<>();
                companyUserQw.eq(SysCompanyUser::getCompanyId, CurrentUserHolder.get().getCompanyId());
                companyUserQw.eq(SysCompanyUser::getWorkNumber , member.getWorkNumber());

                Integer count = companyUserMapper.selectCount(companyUserQw);
                if(count > 0){
                    throw new NcException(ResponseEnum.WROK_NUM_EXISTS);
                }
            }
            //判断手机号和邮箱是否存在
            if(member.getMobile() != null){
                LambdaQueryWrapper<SysUser> userQw = new LambdaQueryWrapper<>();
                userQw.eq(SysUser::getMobile, member.getMobile());

                Integer count = userMapper.selectCount(userQw);
                if(count > 0){
                    throw new NcException(ResponseEnum.USER_MOBILE_EMAIL_EXISTS);
                }
            }



            //创建系统用户
            SysUser user = new SysUser();
            user.setUsername(member.getName());
            user.setMobile(member.getMobile());
            user.setPassword(new BCryptPasswordEncoder().encode("123456"));
            user.setEmail(member.getEmail());
            user.setCreateTime(new Date());
            user.setStatus(member.getEnable() == "可用" ? (short)1: (short)0 );
            user.setLastLoginCompanyId(CurrentUserHolder.get().getCompanyId());
            //保存系统用户
            userMapper.insert(user);

            //创建企业员工， 存储企业员工数据
            SysCompanyUser companyUser = new SysCompanyUser();
            companyUser.setUserId(user.getId());
            companyUser.setUserName(member.getName());
            companyUser.setMobile(member.getMobile());
            companyUser.setCompanyId(CurrentUserHolder.get().getCompanyId());
            companyUser.setCompanyName(CurrentUserHolder.get().getCompanyName());
            //组装部门数据
            if(member.getDepartmentName() != null){
                //根据部门名称，获取部门信息，并组装到 员工表 中
                LambdaQueryWrapper<SysDepartment> departmentQw = new LambdaQueryWrapper<>();
                departmentQw.eq(SysDepartment::getCompanyId, CurrentUserHolder.get().getCompanyId());
                departmentQw.eq(SysDepartment::getName, member.getDepartmentName());

                SysDepartment department = departmentMapper.selectOne(departmentQw);
                if(department != null){
                    companyUser.setDepartmentId(department.getId());
                    companyUser.setDepartmentName(department.getName());
                }
            }

            companyUser.setPost(member.getPosition());
            companyUser.setWorkNumber(member.getWorkNumber());
            companyUser.setEmail(member.getEmail());
            companyUser.setOfficeAddress(member.getWorkAddr());
            companyUser.setRemark(member.getDesc());
            companyUser.setCreateTime(member.getEntryTime());
            companyUser.setEnable("可用".equals(member.getEnable())  ? (short)1: (short)0 );

            companyUserMapper.insert(companyUser);


            //获取角色名称
            String roleName = member.getRoleName();
            //判断角色
            if(StrUtil.isNotEmpty(roleName)){
                LambdaQueryWrapper<SysRole> roleQw = new LambdaQueryWrapper<>();
                roleQw.eq(SysRole::getCompanyId, CurrentUserHolder.get().getCompanyId());
                roleQw.eq(SysRole::getRoleDesc, roleName);

                SysRole role = roleMapper.selectOne(roleQw);
                if(role != null){
                    SysCompanyUserRole companyUserRole = new SysCompanyUserRole();
                    companyUserRole.setCompanyUserId(companyUser.getId());
                    companyUserRole.setRoleId(role.getId());
                    companyUserRole.setCompanyId(CurrentUserHolder.get().getCompanyId());

                    companyUserRoleMapper.insert(companyUserRole);
                }
            }
            SysUser u = new SysUser();
            u.setUsername(user.getUsername());
            u.setPassword("123456");
            manager.registerUser2HuanXing( u);
        }

    }

    @Override
    public SysCompanyUserDTO findCompanyUserByMobile(String mobile) {
        if(mobile == null){
            throw new NcException(ResponseEnum.INVALID_PARAM_ERROR);
        }

        LambdaQueryWrapper<SysCompanyUser> companyUserQw = new LambdaQueryWrapper<>();
        companyUserQw.eq(SysCompanyUser::getMobile, mobile);
        companyUserQw.eq(SysCompanyUser::getCompanyId, CurrentUserHolder.get().getCompanyId());

        SysCompanyUser companyUser = companyUserMapper.selectOne(companyUserQw);
        if(companyUser != null){
            return BeanHelper.copyProperties(companyUser, SysCompanyUserDTO.class);
        }
        return null;
    }

    @Override
    public List<SysCompanyUserDTO> queryAll() {
        Long companyId = CurrentUserHolder.get().getCompanyId();

        LambdaQueryWrapper<SysCompanyUser> companyUserQw = new LambdaQueryWrapper<>();
        companyUserQw.eq(SysCompanyUser::getCompanyId, companyId);
        companyUserQw.eq(SysCompanyUser::getEnable, 1);

        List<SysCompanyUser> sysCompanyUserList = companyUserMapper.selectList(companyUserQw);

        if(CollectionUtil.isNotEmpty(sysCompanyUserList)){
            List<SysCompanyUserDTO> companyUserDTOList = BeanHelper.copyWithCollection(sysCompanyUserList, SysCompanyUserDTO.class);
            return companyUserDTOList;
        }
        return new ArrayList<>();
    }

    @Override
    public SysCompanyUserDTO queryAdminByCompanyId(Long companyId) {
        SysCompanyUser currentAdmin = companyMapper.getCurrentAdmin(companyId);
        if(currentAdmin != null){
            return  BeanHelper.copyProperties(currentAdmin, SysCompanyUserDTO.class);
        }
        return null;
    }


    private void  queryChildrenDepartmentIds(Set<Long> departmentIds , Long parentId) {
        LambdaQueryWrapper<SysDepartment> departmentQw = new LambdaQueryWrapper<>();
        departmentQw.eq(SysDepartment::getCompanyId, CurrentUserHolder.get().getCompanyId());
        departmentQw.eq(SysDepartment::getParentId, parentId);
        List<SysDepartment> departmentList = departmentMapper.selectList(departmentQw);
        if(CollectionUtil.isNotEmpty(departmentList)) {
            Set<Long> ids = departmentList.stream().map(sysDepartment -> {
                return sysDepartment.getId();
            }).collect(Collectors.toSet());
            departmentIds.addAll(ids);
            //循环，递归查询子部门的id
            for (Long id : ids) {
                this.queryChildrenDepartmentIds(departmentIds,id);
            }
        }
    }

    private Set<Long> queryAllDepartmentId() {
        LambdaQueryWrapper<SysDepartment> departmentQw = new LambdaQueryWrapper<>();
        departmentQw.eq(SysDepartment::getCompanyId, CurrentUserHolder.get().getCompanyId());
        List<SysDepartment> departmentList = departmentMapper.selectList(departmentQw);
        if(CollectionUtil.isNotEmpty(departmentList)){
            Set<Long> ids = departmentList.stream().map(sysDepartment -> {
                return sysDepartment.getId();
            }).collect(Collectors.toSet());

            return ids;
        }
        return new HashSet<>();
    }
}
